-module(websocket_handler).
-compile(export_all).

-include("globals.hrl").

%% 初始化数据库
start() -> 
    mnesia:create_schema([node()]),
    mnesia:start(),
    mnesia:create_table(session, [{attributes, record_info(fields, session)}]).

%% 路由分发
dispatcher(Data, Session) ->
    Reg = "/?([a-z]+[a-zA-Z0-9_]*)/([a-z]+[a-zA-Z0-9_]*):(.*)", 
    case re:run(Data, Reg, [global, {capture, all, list}]) of 
        %% 如果解析参数成功, 则交由具体的 控制器-方法 来处理
        {match, [[_FullMatch, Module, Function, Args]]} -> 
            Handler = list_to_atom(lists:concat([Module, "_handler"])), 
            {NewSession, Message} = Handler:handle_info({list_to_atom(Function), process_args(Args), Session}), %% 以json形式返回处理过的数组
            {NewSession, to_json(Message)};
        nomatch -> 
            {Session, to_json(#message{code = ?LINE, message = "no handler found."})}
    end.

%% 判断模块是否存在
module_exists(Module) ->
    case erlang:module_loaded(Module) of 
        true -> next;
        _ -> code:load_file(Module)
    end,
    erlang:function_exported(Module, "module_info", 0).
    
%% 断开连接时处理
handler_close(UserId) -> cache_remove(UserId).

%% 写入数据库当前会话信息
cache_insert(Session) -> 
    mnesia:transaction(fun() -> mnesia:write(#session{user_id = Session#session.user_id, user_name = Session#session.user_name, socket = Session#session.socket, connected = cur_time()}) end).

%% 从数据库删除此用户相关会话信息
cache_remove(Session) -> 
    mnesia:transaction(fun() -> mnesia:delete({session, Session#session.user_id}) end).

%% 当前时间
cur_time() -> {date(), time()}.

%% 处理参数
process_args(Data) -> 
    Reg = "([a-zA-Z0-9_]+)=([a-zA-Z0-9_]+)&?",
    case re:run(Data, Reg, [global, {capture, all, list}]) of 
        {match, Result} -> [{list_to_atom(ArgName), ArgValue} || [_, ArgName, ArgValue] <- Result];
        nomatch -> [];
        R -> io:format("Error Queries: ~p~n", [R])
    end.

%% 取得参数中的值
get_query(Data, ArgName) -> 
    case [{K, V} || {K, V} <- Data, K =:= ArgName] of
        [{_Key, Val}] -> Val;
        _ -> []
    end.

%% 生成json数组形式
to_json(Result) -> 
    lists:concat([
        "{", 
            "code:", Result#message.code, ",",
            "type:", Result#message.type, ",",
            "state:", Result#message.state, ",",
            "message:", "\"", Result#message.message, "\"",
        "}"
    ]).

%% 推送消息给相应的用户
push_user_message(UserId, Data) ->
    case mnesia:transaction(fun() -> mnesia:read({session, UserId}) end) of 
        {atomic, [Session]} -> websocket_server:send_data(Session#session.socket, to_json(Data));
        _R -> next
    end.
